package stark.app.function.speechrec;

import android.Manifest;
import android.graphics.Rect;
import android.media.AudioFormat;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.PermissionUtils;
import com.blankj.utilcode.util.SizeUtils;
import com.blankj.utilcode.util.TimeUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.stark.media.recorder.RawAudioRecorder;
import com.stark.speechrec.lib.ShortSpeechRecognizer;

import stark.app.R;
import stark.app.databinding.ActivitySpeechRecDemoBinding;
import stark.common.apis.base.ShortSpeechRecRet;
import stark.common.base.IReqRetCallback;
import stark.common.basic.base.BaseNoModelActivity;
import stark.common.basic.media.audio.PcmAudioPlayer;
import stark.common.basic.utils.DialogUtil;
import stark.common.basic.utils.FileUtil;

/**
 * Author：daizhongbin on 2022/3/15
 * Email：1027154338@qq.com
 * Desc:
 */
public class SpeechRecDemoActivity extends BaseNoModelActivity<ActivitySpeechRecDemoBinding> {

    private static final String TAG = SpeechRecDemoActivity.class.getSimpleName();
    private ShortSpeechRecognizer mSpeechRecognizer = ShortSpeechRecognizer.getInstance();
    private Handler mHandler = new Handler(Looper.getMainLooper());
    private SpeechRecAdapter mSpeechRecAdapter;

    @Override
    protected int onCreate() {
        return R.layout.activity_speech_rec_demo;
    }

    @Override
    protected void initView() {
        mSpeechRecognizer.setStateListener(new RawAudioRecorder.IStateListener() {
            @Override
            public void onStateChanged(@NonNull RawAudioRecorder.State oldState, @NonNull RawAudioRecorder.State newState) {
                if (isFinishing() || isDestroyed()) return;

                if (newState == RawAudioRecorder.State.IDLE) {
                    //变为了空闲，说明录制结束，则开始识别
                    mDataBinding.btnStartStop.setText("开始录制");
                    mDataBinding.btnPauseResume.setVisibility(View.GONE);
                    mHandler.removeCallbacks(taskUpdateTime);
                    startRecognize();
                } else {
                    mDataBinding.btnStartStop.setText("停止录制");
                    mDataBinding.btnPauseResume.setVisibility(View.VISIBLE);
                    if (newState == RawAudioRecorder.State.PAUSE) {
                        mDataBinding.btnPauseResume.setText("恢复录制");
                        mHandler.removeCallbacks(taskUpdateTime);
                    } else {
                        mDataBinding.btnPauseResume.setText("暂停录制");
                        mHandler.post(taskUpdateTime);
                    }
                }
            }
        });

        mDataBinding.btnStartStop.setOnClickListener(v -> {
            RawAudioRecorder.State state = mSpeechRecognizer.getState();
            if (state == RawAudioRecorder.State.IDLE) {
                startRecAudio();
            } else {
                stopRecAudio();
            }
        });
        mDataBinding.btnPauseResume.setOnClickListener(v -> {
            RawAudioRecorder.State state = mSpeechRecognizer.getState();
            if (state == RawAudioRecorder.State.REC) {
                mSpeechRecognizer.pauseRecAudio();
            } else {
                mSpeechRecognizer.resumeRecAudio();
            }
        });

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mDataBinding.rvRec.setLayoutManager(layoutManager);
        mDataBinding.rvRec.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
                outRect.set(0, SizeUtils.dp2px(10), 0, 0);
            }
        });
        mSpeechRecAdapter = new SpeechRecAdapter();
        mSpeechRecAdapter.setOnItemClickListener(this);
        mSpeechRecAdapter.setOnItemLongClickListener((adapter, view, position) -> {
            if (mPcmAudioPlayer != null) {
                mPcmAudioPlayer.stop();
            }
            DialogUtil.asConfirm(SpeechRecDemoActivity.this, "删除提示", "确认删除该记录？", "取消", "确定", () -> {
                int playPos = mSpeechRecAdapter.getPlayPos();
                if (playPos == position) {
                    mSpeechRecAdapter.setPlayPos(-1);
                }
                SpeechRecRecordManager.getInstance().delRecord(mSpeechRecAdapter.getItem(position));
                mSpeechRecAdapter.removeAt(position);
            }, null, false);
            return false;
        });
        mSpeechRecAdapter.setList(SpeechRecRecordManager.getInstance().getRecRecords());
        mDataBinding.rvRec.setAdapter(mSpeechRecAdapter);

        mDataBinding.ivPlayState.setOnClickListener((view) -> {
            if (mPcmAudioPlayer == null) return;
            if (mPcmAudioPlayer.getState() == PcmAudioPlayer.State.PLAYING) {
                mPcmAudioPlayer.pause();
            } else if (mPcmAudioPlayer.getState() == PcmAudioPlayer.State.PAUSE) {
                mPcmAudioPlayer.resume();
            }
        });
    }

    @Override
    protected void initData() {
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mPcmAudioPlayer != null) {
            mPcmAudioPlayer.stop();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSpeechRecognizer.stopRecAudio();
        mHandler.removeCallbacksAndMessages(null);
    }

    @Override
    protected void onItemClickCallback(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
        SpeechRecRecord record = mSpeechRecAdapter.getItem(position);
        mSpeechRecAdapter.setPlayPos(position);
        playPcm(record.filePath);
    }

    private void startRecAudio() {
        PermissionUtils.permission(Manifest.permission.RECORD_AUDIO)
                .callback(new PermissionUtils.SimpleCallback() {
                    @Override
                    public void onGranted() {
                        String recFilePath = FileUtil.generateFilePathByName("stt", "stt.pcm");
                        mSpeechRecognizer.startRecAudio(recFilePath);
                    }

                    @Override
                    public void onDenied() {
                        ToastUtils.showShort("未授予权限");
                    }
                })
                .request();
    }

    private void stopRecAudio() {
        mSpeechRecognizer.stopRecAudio();
    }

    private void startRecognize() {
        showDialog("识别中...");
        mSpeechRecognizer.startRecognize(this, mSpeechRecognizer.getRecFilePath(), new IReqRetCallback<ShortSpeechRecRet>() {
            @Override
            public void onResult(boolean success, String msg, @Nullable ShortSpeechRecRet result) {
                dismissDialog();
                if (result == null || result.result == null) {
                    ToastUtils.showShort(msg);
                    return;
                }
                Log.e(TAG, "result = " + result);
                StringBuilder builder = new StringBuilder();
                StringBuilder builder1 = new StringBuilder();
                builder.append("识别结果为：\n");
                for (String str : result.result) {
                    builder.append(str);
                    builder1.append(str);
                }
                mDataBinding.tvRet.setText(builder.toString());
                addSpeechRecRecord(builder1.toString(), mSpeechRecognizer.getRecFilePath());
            }
        });
    }

    private Runnable taskUpdateTime = new Runnable() {
        @Override
        public void run() {
            long duration = mSpeechRecognizer.getRecDuration();
            mDataBinding.tvTime.setText(TimeUtils.millis2String(duration, "mm:ss"));
            mHandler.postDelayed(this, 500);
        }
    };

    private void addSpeechRecRecord(String text, String filePath) {
        String newFilePath = FileUtils.getDirName(filePath) + System.currentTimeMillis() + ".pcm";
        FileUtils.copy(filePath, newFilePath);
        SpeechRecRecord record = new SpeechRecRecord();
        record.filePath = newFilePath;
        record.text = text;
        //这里因为是demo，所以用的内部用的是SharedPreference来实现持久化存储的，建议使用数据库
        SpeechRecRecordManager.getInstance().addRecord(record);
        mSpeechRecAdapter.setList(SpeechRecRecordManager.getInstance().getRecRecords());
    }

    private PcmAudioPlayer mPcmAudioPlayer;

    private long totalDuration = 0;

    private void playPcm(String filePath) {
        if (mPcmAudioPlayer == null) {
            mPcmAudioPlayer = new PcmAudioPlayer();
            mPcmAudioPlayer.setStateListener(state -> {
                //播放状态变化。在这里可以处理播放状态控件的变化
                if (state == PcmAudioPlayer.State.PLAYING) {
                    mDataBinding.ivPlayState.setImageResource(com.stark.audio.edit.R.drawable.ic_ae_pause);
                } else {
                    mDataBinding.ivPlayState.setImageResource(com.stark.audio.edit.R.drawable.ic_ae_play);
                }
            });
            mPcmAudioPlayer.setPlayDurationListener(playDuration -> {
                //播放时长变化。在这里可以实现更新播放时长的控件
                mDataBinding.progressBar.setProgress(playDuration);
                mDataBinding.tvPlayTime.setText(playDuration + "/" + totalDuration);
            });
        }
        PcmAudioPlayer.PcmInfo pcmInfo = new PcmAudioPlayer.PcmInfo(AudioFormat.ENCODING_PCM_16BIT, 16000, AudioFormat.CHANNEL_OUT_MONO);
        //下面方法可以获取文件总时长
        long duration = PcmAudioPlayer.getDuration(filePath, pcmInfo);
        totalDuration = duration;
        mDataBinding.progressBar.setMax((int) duration);
        mDataBinding.progressBar.setProgress(0);
        mPcmAudioPlayer.play(filePath, pcmInfo);
    }
}
